﻿using System;
using System.Collections.Generic;
using System.Text;
using AgilePlannerDT.Data;
using AgilePlannerDT.Persister.Impl.Socket;
using System.Xml.Schema;
using System.Xml;
using System.IO;

namespace AgilePlannerDT.Data.Impl
{
    public class MessageDataObject : Message
    {
        #region Constants

        public const int RAW_MESSAGE = 0;

        public const int EXCEPTION = -1;

        public const int CONNECT = 99;

        public const int DISCONNECT = 98;

        public const int AUTH_FAIL = 97;

        public const int GET_PROJECT_NAMES = 1;

        public const int LOAD = 2;

        public const int TIMEBOX_LOAD = 3;

        public const int SAVE = 4;

        public const int SAVE_AS = 5;

        public const int UPLOAD = 6;

        public const int DOWNLOAD = 7;

        public const int GET_PROJECT_FILES_NAME = 8;

        public const int CREATE_BACKLOG = 10;

        public const int DELETE_BACKLOG = 11;

        public const int DELETE_CARD = 12;

        public const int UNDELETE_CARD = 13;

        public const int UPDATE_BACKLOG = 14;

        public const int CREATE_ITERATION = 20;

        public const int DELETE_ITERATION = 21;

        public const int UNDELETE_ITERATION = 23;

        public const int UPDATE_ITERATION = 24;

        public const int REMOVE_USER = 27;

        public const int CREATE_STORYCARD = 40;

        public const int DELETE_STORYCARD = 41;

        public const int MOVE_STORYCARD_TO_NEW_PARENT = 43;

        public const int UNDELETE_STORYCARD = 46;

        public const int UPDATE_STORYCARD = 48;

        public const int UPDATE_CARD = 48;

        public const int UPDATE_LEGEND = 49;

        public const int ADD_USER = 50;

        public const int MOUSE_MOVE = 60;

        public const int BRING_TO_FRONT = 61;

        public const int DELETE_REMOTE_MOUSE = 62;

        public const int KEYSTROKE = 63;

        public const int CREATE_PROJECT = 70;

        public const int GET_ACCEPTANCE_TEST_REQ = 80;

        public const int GET_ACCEPTANCE_TEST_RESP = 81;

        public const int ARRANGE_PROJECT = 82;

        public const int SYNCH_PROJECT = 83;

        public const int LOGIN = 84;

        public const int LOST_CONNECTION = 85;

        public const int REMOVE_REMOTE_MOUSE = 86;

        public const int CONNECT_TO_RALLY = 87;

        public const int MINIMIZE_CARD = 89;
        
        public const int UPDATE_PROJECT = 90;

        public const int SYNC_WITH_JAZZ = 101;

        public const int RESTORE_TO_JAZZ = 102;

        public const int START_VOTING = 1001;

        public const int STOP_VOTING = 1002;

        public const int VOTE_CARD = 1003;

        public const int CLEAR_VOTES = 1004;


        #endregion

        #region Attributes

        protected long senderid;
        protected int mtype, etype;
        protected object message;
        protected Dictionary<string, string> data;

        #endregion

        #region Constructors

        public MessageDataObject(long senderid, int mtype, int etype, object message, Dictionary<string, string> data)
        {
            this.senderid = senderid;
            this.mtype = mtype;
            this.etype = etype;
            this.message = message;
            this.data = data;
        }

        public MessageDataObject(long senderid, int mtype, int etype, Object message)
            : this(senderid, mtype, etype, message, new Dictionary<string, string>())
        {
        }

        public MessageDataObject(long senderid, int mtype, Object message, Dictionary<string, string> data)
            : this(senderid, mtype, 0, message, data)
        {
        }

        public MessageDataObject(long senderid, int mtype, Object message)
            : this(senderid, mtype, 0, message, new Dictionary<string, string>())
        {
        }


        public MessageDataObject(int mtype, Object message)
            : this(0, mtype, 0, message, new Dictionary<string, string>())
        {
        }

        public MessageDataObject(long senderid, int mtype)
            : this(senderid, mtype, 0, null, new Dictionary<string, string>())
        {
        }

        public MessageDataObject(int mtype)
            : this(0, mtype, 0, null, new Dictionary<string, string>())
        {
        }

        public MessageDataObject(int mtype, Dictionary<string, string> data)
            : this(0, mtype, null, data)
        {
        }

        #endregion

        #region Message Members

        public long Sender
        {
            get { return this.senderid; }
            set { this.senderid = value; }
        }

        public object Message
        {
            get { return this.message; }
            set { this.message = value; }
        }

        public int MessageType
        {
            get { return this.mtype; }
            set { this.mtype = value; }
        }

        public int ExceptionType
        {
            get { return this.etype; }
            set { this.etype = value; }
        }

        public Dictionary<string, string> Data
        {
            get { return this.data; }
            set { this.data = value; }
        }

        #endregion

        // override object.Equals
        public override bool Equals(object obj)
        {
            if (obj == null || GetType() != obj.GetType())
            {
                return false;
            }
            Message other = (Message)obj;
            return
                ExceptionType.Equals(other.ExceptionType) &&
                Sender.Equals(other.Sender) &&
                MessageType.Equals(other.MessageType) &&
                Message.Equals(other);
        }

        // override object.GetHashCode
        public override int GetHashCode()
        {
            return base.GetHashCode();
        }

        #region IXmlSerializable Members

        public XmlSchema GetSchema()
        {
            return null;
        }
         
        public void ReadXml(String xml)
        {
            StringReader stringReader = new StringReader(xml);
            XmlTextReader reader = new XmlTextReader(stringReader);
            reader.WhitespaceHandling = WhitespaceHandling.Significant;
            reader.Read();
            ReadXml(reader);
        }

        public void ReadXml(XmlReader reader)
        {

            if (reader.GetAttribute("etype") == null)
            {
                //System.Windows.MessageBox.Show("ETYPE IS NULL!!!");
            }
            else
            {
                //System.Windows.MessageBox.Show("ETYPE IS NOT NULL = "+reader.GetAttribute("etype"));
                ExceptionType = int.Parse(reader.GetAttribute("etype"));
                MessageType = int.Parse(reader.GetAttribute("mtype"));
                Sender = long.Parse(reader.GetAttribute("sender"));
                //Console.WriteLine("Sender ID is " + Sender);
            }
            
            Data = new Dictionary<string, string>();

            while (reader.Read())
            {
                switch (reader.NodeType)
                {
                    case(XmlNodeType.Element):
      
                        if(reader.LocalName.Equals("MouseMove"))
                        {
                            MouseMove move = new MouseMoveDataObject();
                            move.ReadXml(reader);
                            Message = move;
                        }
                        else if (reader.LocalName.Equals("StoryCard"))
                        {
                            StoryCard sc = new StoryCardDataObject();
                            sc.ReadXml(reader);
                            Message = sc;
                        }
                        else if (reader.LocalName.Equals("Iteration"))
                        {
                            Iteration iter = new IterationDataObject();
                            iter.ReadXml(reader);
                            Message = iter;
                        }
                        else if (reader.LocalName.Equals("Backlog"))
                        {
                            Backlog back = new BacklogDataObject();
                            back.ReadXml(reader);
                            Message = back;
                        }
                        else if (reader.LocalName.Equals("Legend"))
                        {
                            Legend lgnd = new LegendDataObject();
                            lgnd.ReadXml(reader);
                            Message = lgnd;
                        }
                        else if (reader.LocalName.Equals("Project"))
                        {
                            Project prj = new ProjectDataObject();
                            prj.ReadXml(reader);
                            Message = prj;
                        }
                        else if (reader.LocalName.Equals("Data"))
                        {
                            if (reader.IsEmptyElement)
                                break;
                            reader.Read();
                            do
                            {
                                data.Add(reader.GetAttribute("key"), reader.GetAttribute("value"));
                            } while (reader.ReadToNextSibling(reader.LocalName));
                        }
                        else if (reader.LocalName.Equals("ProjectNameList"))
                        {
                            if (reader.IsEmptyElement)
                                break;
                            List<String> projectList = new List<string>();
                            reader.Read();
                            do
                            {
                                projectList.Add(reader.GetAttribute("name"));
                            
                            } while (reader.ReadToNextSibling(reader.LocalName));
                            Message = projectList;
                          //  reader.read();
                        }
                        else if(reader.LocalName.Equals("DisconnectData"))
                        {
                            Message = Convert.ToInt32(reader.GetAttribute("clientid"));
                        }
                        else if (reader.LocalName.Equals("LiveUpdate"))
                        {
                            LiveUpdate update = new LiveUpdateDataObject();
                            update.ReadXml(reader);
                            Message = update;
                        }
                        else if (reader.LocalName.Equals("VoteDot"))
                        {
                            VoteDot dot = new VoteDotObject();
                            dot.ReadXml(reader);
                            Message = dot;
                        }
                        else if (reader.LocalName.Equals("ElementTypeBody"))
                        {
                            long id;
                            if (long.TryParse(reader.GetAttribute("Body"), out id))
                                Message = id;
                            else
                                Message = reader.GetAttribute("Body");
                        }
                        break;
                }
            }

        }

        public void WriteXml(XmlWriter writer)
        {
            writer.WriteStartElement("Message");
            writer.WriteAttributeString("etype", etype.ToString());
            writer.WriteAttributeString("mtype", mtype.ToString());
            writer.WriteAttributeString("sender", senderid.ToString());

            if (message != null)
            {
                if (message is MouseMove)
                {
                    ((MouseMove)message).WriteXml(writer);
                }

                else if (message is StoryCard)
                {
                    ((StoryCard)message).WriteXml(writer);
                }
                else if (message is Iteration)
                {
                    ((Iteration)message).WriteXml(writer);
                }
                else if (message is Backlog)
                {
                    ((Backlog)message).WriteXml(writer);
                }
                else if (message is Project)
                {
                    ((Project)message).WriteXml(writer);
                }
                else if (message is Legend)
                {
                    ((Legend)message).WriteXml(writer);
                }
                else if (message is string || message is long)
                {
                    writer.WriteStartElement("ElementTypeBody");
                    writer.WriteAttributeString("Body", message.ToString());
                    writer.WriteEndElement();
                }
                else if (message is LiveUpdate)
                {
                    ((LiveUpdate)message).WriteXml(writer);
                }
                else if (message is TeamMember)
                {
                    ((TeamMember)message).WriteXml(writer);
                }
                else if (message is VoteDot)
                {
                    ((VoteDot)message).WriteXml(writer);
                }
            }

            if (data.Keys.Count > 0)
            {
                writer.WriteStartElement("Data");
                Dictionary<string, string>.KeyCollection.Enumerator keys = data.Keys.GetEnumerator();
                while (keys.MoveNext())
                {
                    writer.WriteStartElement("Entry");
                    writer.WriteAttributeString("key", keys.Current);
                    string value;
                    data.TryGetValue(keys.Current, out value);
                    writer.WriteAttributeString("value", value);
                    writer.WriteEndElement();

                }
                writer.WriteEndElement();
            }

            writer.WriteEndElement();
          //  writer.WriteEndDocument();
        }
   

        #endregion

        
    }
}
